﻿/*************************************************************************
 * Created by OhZee Creative, LLC
 * 2013
 * This code is licensed under Microsoft Public License (Ms-PL)
 * http://opensource.org/licenses/ms-pl
 * http://ozcontrols.codeplex.com/
 *************************************************************************/

namespace OhZeeCreative.UI.Controls
{
    using System;
    using System.ComponentModel;
    using OhZeeCreative.Helpers;

#if SILVERLIGHT
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Shapes;
#endif
#if NETFX_CORE
    using Windows.Foundation;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Shapes;
#endif

    /// <summary>
    /// Checkers control creates a checkerboard pattern with adjustable cell sizes, foreground and background colors. This is useful to quickly create a game board or to create a subtle background that differentiates areas or surfaces of your app. It's very efficient because it only uses one UIElement to draw the graphic.
    /// </summary>    
    [EditorBrowsableAttribute(EditorBrowsableState.Always)]
    [TemplatePart(Name = Checkers.TEMPLATE_PART, Type = typeof(Polygon))]
	public sealed class Checkers : Control
	{
        public const string TEMPLATE_PART = "polygon";

		private Polygon polygon;
		public static readonly DependencyProperty CellWidthProperty = DependencyProperty.Register("CellWidth", typeof(double), typeof(Checkers), new PropertyMetadata(50.0, CellWidthPropertyChanged));
		public static readonly DependencyProperty CellHeightProperty = DependencyProperty.Register("CellHeight", typeof(double), typeof(Checkers), new PropertyMetadata(50.0, CellHeightPropertyChanged));

		private static void CellWidthPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
		{
			Checkers grid = (Checkers)o;

			if (!DependencyHelper.CoerceMinimum(grid, e, CellWidthProperty, 0.0, inclusive: false))
			{
				grid.Update();
			}
		}

		private static void CellHeightPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
		{
			Checkers grid = (Checkers)o;

			if (!DependencyHelper.CoerceMinimum(grid, e, CellHeightProperty, 0.0, inclusive: false))
			{
				grid.Update();
			}
		}

        /// <summary>
        /// Gets or sets the width of each cell in pixels.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Always)]
		public double CellWidth
		{
			get { return (double)GetValue(CellWidthProperty); }
			set { SetValue(CellWidthProperty, value); }
		}

        /// <summary>
        /// Gets or sets the height of each cell in pixels.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Always)]
		public double CellHeight
		{
			get { return (double)GetValue(CellHeightProperty); }
			set { SetValue(CellHeightProperty, value); }
		}		
		
		public Checkers()
		{
			this.DefaultStyleKey = typeof(Checkers);

			this.SizeChanged += (s, e) => { this.Update(); };
		}

#if SILVERLIGHT
        public override void OnApplyTemplate()
#endif
#if NETFX_CORE
    	protected override void OnApplyTemplate()
#endif		
		{
            this.polygon = this.GetTemplateChild(Checkers.TEMPLATE_PART) as Polygon;
            this.Update();
		}

		private void Update()
		{
			if (this.polygon == null || this.CellWidth <= 0 || this.CellHeight <= 0)
			{
				return;
			}

			int columns = (int) Math.Ceiling(this.ActualWidth / this.CellWidth);
			int rows = (int)Math.Ceiling(this.ActualHeight / this.CellHeight);

			if (columns == 0 || rows == 0)
			{
				return;
			}

			double height = this.CellHeight * rows;
			double width = this.CellWidth * columns;

			this.polygon.Points.Clear();

#if SILVERLIGHT
            Point point = new Point();
#endif
#if NETFX_CORE
			Point point;
#endif

			bool up;

			bool oddRows = (rows % 2) == 1;

			if (oddRows)
			{
				up = false;
				//point.Y = 0;
			}
			else
			{
				// Start from the bottom
				up = true;				
				point.Y = height;				
			}

			this.polygon.Points.Add(point);

			// Go down and up towards the right

			double deltaX = this.CellWidth;
			for (int col = 0; col < columns; col++, up = !up)
			{
				point.Y = up ? 0 : height;
				this.polygon.Points.Add(point);
				point.X += deltaX;
				this.polygon.Points.Add(point);
			}
			
			// Make sure to stop at the opposite corner
			if (oddRows && point.Y == 0)
			{
				point.Y = height;
				this.polygon.Points.Add(point);
			}
			else if (!oddRows && point.Y == height)
			{
				point.Y = 0;
				this.polygon.Points.Add(point);
			}

			bool right = false;
			// Go left and right towards the origin
			double deltaY = oddRows ? -this.CellHeight : this.CellHeight;
			for (int row = 0; row < rows; row++, right = !right)
			{
				point.X = right ? 0 : width;
				this.polygon.Points.Add(point);
				point.Y += deltaY;
				this.polygon.Points.Add(point);
			}

			// Make sure to finish
			if (point.X == 0)
			{
				point.X = width;
			}
			else
			{
				point.X = 0.0;
			}

			this.polygon.Points.Add(point);			
		}
	}
}
